/**
 * 抽象工厂模式
 * 抽象工厂模式提供创建一系列相关或相互依赖对象的接口，而无需指定它们具体的类。
 * 当存在多个产品系列，而客户端只使用一个系列的产品时，可以考虑使用抽象工厂模式。
 * 缺点：当增加一个新系列的产品时，不仅需要现实具体的产品类，还需要增加一个新的创建接口，扩展相对困难。
 * 以下代码以白色衣服和黑色衣服为例：白色衣服为一个产品系列，黑色衣服为一个产品系列。
 * 白色上衣搭配白色裤子，黑色上衣搭配黑色裤子。每个系列的衣服由一个对应的工厂创建，
 * 这样一个工厂创建的衣服能保证衣服为同一个系列。
 */
#pragma once

#include <string>

using namespace std;

namespace abstractfactory
{
//抽象上衣类
class AbstractCoat
{
public:
    virtual const string color() const = 0;
};

//黑色上衣类
class BlackCoat : public AbstractCoat
{
public:
    const string color() const override {
        return "Black Coat";
    }
};

//白色上衣类
class WhiteCoat : public AbstractCoat
{
public:
    const string color() const override {
        return "White Coat";
    }
};

//抽象裤子类
class AbstractPants
{
public:
    virtual const string color() const = 0;
};

//黑色裤子类
class BlackPants : public AbstractPants
{
public:
    const string color() const override {
        return "Black Pants";
    }
};

//黑色裤子类
class WhitePants : public AbstractPants
{
public:
    const string color() const override {
        return "White Pants";
    }
};

//抽象工厂类，提供衣服创建接口
class AbstractFactory
{
public:
    //上衣创建接口
    virtual AbstractCoat* createCoat() const = 0;
    //裤子创建接口
    virtual AbstractPants* createPants() const = 0;
};

class WhiteFactory : public AbstractFactory
{
public:
    AbstractCoat* createCoat() const override {
        return new WhiteCoat();
    }
    AbstractPants* createPants() const override {
        return new WhitePants();
    }
};

class BlackFactory : public AbstractFactory
{
public:
    AbstractCoat* createCoat() const override {
        return new BlackCoat();
    }
    AbstractPants* createPants() const override {
        return new BlackPants();
    }
};

void ClientCode(AbstractFactory* factory)
{
    unique_ptr<AbstractCoat> coat(factory->createCoat());
    unique_ptr<AbstractPants> pants(factory->createPants());
    cout << "Coat Color:" << coat->color() << endl;
    cout << "Pants Color:" << pants->color() << endl;
}

} // namespace abstractfactory